﻿#include "login_logic.h"
#include "LoginServer.h"
#include "../share/MessageDef.h"
#include "../share/GameHostManager.h"
#include "../share/tplmgr.h"
#include "../share/dirtyword.h"
#include "../share/proxyclient_service.h"
#include "loginobj_manager.h"
#include "../share/time_module.h"
#include "login_queue_mgr.h"

CLoginAccount::CLoginAccount()
{
	account_id_ = 0;
	login_status_ = ELOGIN_STATUS_NONE;
	user_name_ = "";
	socket_fd_ = 0;
	time_ = 0;
}

CLoginAccount::~CLoginAccount()
{

}

void CLoginAccount::SetUserName(const std::string& user_name)
{
	user_name_ = user_name;
}

int CLoginAccount::ChangeLoginStatus(EAccountLoginStatus status)
{
	login_status_ = status;
	return ::common::SUCCEED;
}

void CLoginLogic::Initialize()
{
	registe_client_msg(lua_general_message_req, CLoginLogic::SGeneralLuaMessageReq);
	registe_client_msg(login_check_account_req, CLoginLogic::SCheckAccountReq);
	registe_client_msg(login_player_login_req, CLoginLogic::SPlayerLoginReq);
	registe_client_msg(login_create_player_req, CLoginLogic::SPlayerRegisterReq);

	registe_server_msg(lua_general_message_req, CLoginLogic::SGeneralLuaMessageReqServer);
	registe_server_msg(g2l_create_player_ret, CLoginLogic::G2LPlayerRegisterResponse);
	registe_server_msg(g2l_login_check_account_ret, CLoginLogic::G2LPlayerCheckAccountResponse);
	registe_server_msg(g2l_player_login_ret, CLoginLogic::G2LPlayerLoginResponse);
	registe_server_msg(g2l_gameserver_start_notify, CLoginLogic::G2LGameServerStartNotify);
	registe_server_msg(g2l_player_count_report, CLoginLogic::C2LGamePlayerNumReport);

	game_start_ = false;

	test_timer_.TimerInit(30 * 1000);
	test_timer_.TimerStart();
}

void CLoginLogic::SGeneralLuaMessageReq(const CJsonMessageBase& msg)
{
	LOG_ERROR("default", "login server cant do lua func %d");
}

void CLoginLogic::SGeneralLuaMessageReqServer(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	LOG_ERROR("default", "login cant has lua manager!");
}

void CLoginLogic::SCheckAccountReq(const CJsonMessageBase& msg)
{
	//	这个协议是用户登录的第一个协议。
	//	不需要pplayer检查。
	const Json::Value& m_jv = msg.GetJsonValue();
	if (!m_jv.isMember("msgid"))
	{
		return;
	}

	uint32_t _accountId = m_jv["account"].asUInt();
	uint32_t _areaId = m_jv["areaId"].asUInt();

	// 检查用户是否在限制名单里
	if (CTPLManager::GetInstance().isLimitAccount(_accountId))
	{
		LOG_ERROR("default", "this account is limit");
		return;
	}

	if (_accountId < 10000)
	{
		return;
	}

	uint32_t mSocketId = msg.GetFromSocketId();

	if (!CLoginLogic::GetInstance().game_start())
	{
		CLoginLogic::GetInstance().SendCheckAccountRes(mSocketId, ::common::ERR_LOGIN_GAMESERVER_NOT_START, _accountId);
		return;
	}

	// 看看game现在是否还连接正常
	if (CLoginQueueMgr::GetInstance().game_last_update_time() + 3 < CUR_SEC )
	{
		CLoginLogic::GetInstance().SendCheckAccountRes(mSocketId, ::common::ERR_LOGIN_GAMESERVER_NOT_START, _accountId);
		return;
	}

	// 检查该账户是否已经存在
	int32_t ret = CLoginLogic::GetInstance().CheckAccount(_accountId, mSocketId);
	if (ret != ::common::SUCCEED)
	{
		CLoginLogic::GetInstance().SendCheckAccountRes(mSocketId, ret, _accountId);
		return;
	}

	CLoginQueueMgr::GetInstance().AddToLoginQueue(mSocketId, _accountId);

	return;
}

void CLoginLogic::SPlayerLoginReq(const CJsonMessageBase& msg)
{
	const Json::Value& m_jv = msg.GetJsonValue();
	if (!m_jv.isMember("msgid"))
	{
		return;
	}

	uint32_t _accountId = m_jv["account"].asUInt();
	uint32_t _playerId = m_jv["playerId"].asUInt();
	uint32_t _areaId = m_jv["areaId"].asUInt();
	std::string _clientVersion = "1.0";// m_jv["cv"].asString();
									   //uint32_t _clientVersion = m_jv["cv"].asUInt();
	std::string _appKey = m_jv["appKey"].asString();
	std::string _appSecret = m_jv["appSecret"].asString();
	std::string _pubKey = m_jv["pubKey"].asString();
	int32_t fd = msg.GetFromSocketId();

	int32_t ret = CLoginLogic::GetInstance().CheckConnect(_accountId, fd);
	if (ret != ::common::SUCCEED)
	{
		LOG_ERROR("default", "<login> check connect err[%d]", ret);
		CLoginLogic::GetInstance().DoLoginResponse(ret, fd);
		CLoginLogic::GetInstance().DespawnClient(fd);
		return;
	}
	CLoginAccount* login_account = CLoginLogic::GetInstance().GetLoginAccount(_accountId);
	if (login_account == NULL)
	{
		LOG_ERROR("default", "<login> login_account is null [%d][%d]", _accountId, fd);
		return;
	}

	// 没有验证过账号直接过来登陆？肯定不行
	if (login_account->GetLoginStatus() != ELOGIN_STATUS_CHECKACCOUNT_END)
	{
		LOG_ERROR("default", "<login> login account status is err[%d]", login_account->GetLoginStatus());
		return;
	}

	login_account->ChangeLoginStatus(ELOGIN_STATUS_LOGIN_BEGIN);
	//	uint32_t _clientVersion = 1;
	Json::Value request;
	request["account"] = _accountId;
	request["playerId"] = _playerId;
	request["areaid"] = _areaId;
	std::string req = JsonWriter(request);
	send_2_game(l2g_player_login_req, req);
	return;
}

void CLoginLogic::SPlayerRegisterReq(const CJsonMessageBase& msg)
{
	const Json::Value& m_jv = msg.GetJsonValue();
	if (!m_jv.isMember("msgid"))
	{
		return;
	}

	uint32_t _accountId = m_jv["account"].asUInt();
	std::string _name = m_jv["name"].asString();
	uint32_t _areaId = m_jv["areaId"].asUInt();
	std::string _clientVersion = "1.0";// m_jv["cv"].asString();
	uint32_t _heroId = m_jv["heroId"].asUInt();
	std::string _udid = m_jv["udid"].asString();
	std::string _appKey = m_jv["appKey"].asString();
	std::string _appSecret = m_jv["appSecret"].asString();
	std::string _pubKey = m_jv["pubKey"].asString();
	int32_t fd = msg.GetFromSocketId();
	int32_t ret = CLoginLogic::GetInstance().CheckConnect(_accountId, msg.GetFromSocketId());
	if (ret != ::common::SUCCEED)
	{
		LOG_ERROR("default", "<login> check connect err[%d]", ret);
		CLoginLogic::GetInstance().DoRegisterResponse(ret, fd);
		return;
	}

	// 名字长度检查
	if ((int32_t)_name.length() > 32)
	{
		LOG_ERROR("default", "<login> check name length err[%d > 32]", _name.length());
		CLoginLogic::GetInstance().DoRegisterResponse(::common::ERR_LOGIN_NAME_LENGTH_ERR, fd);
		return;
	}
	// 账号ID检查
	if (_accountId < 10000)
	{
		LOG_ERROR("default", "<login> check accountid err[%d]", _accountId);
		CLoginLogic::GetInstance().DoRegisterResponse(::common::ERR_LOGIN_ACCOUNTID_ERR, fd);
		return;
	}

	//判断是否有回车换行
	std::string role_name_str = _name.c_str();
	std::string::size_type idx = role_name_str.find("\n");
	if (idx != std::string::npos)
	{
		LOG_INFO("default", "name have dirtyword[%s]", _name.c_str());
		CLoginLogic::GetInstance().DoRegisterResponse(::common::ERR_LOGIN_NAME_DIRTYWORD_ERR, fd);
		return;
	}

	if (CDirtyWord::GetInstance().OI_Dirty_Check(3, (char*)_name.c_str(), 0) != 0)
	{
		LOG_INFO("default", "name have dirtyword[%s]!", _name.c_str());
		CLoginLogic::GetInstance().DoRegisterResponse(::common::ERR_LOGIN_NAME_DIRTYWORD_ERR, fd);
		return;
	}

	CLoginAccount* login_account = CLoginLogic::GetInstance().GetLoginAccount(_accountId);
	if (login_account == NULL)
	{
		LOG_ERROR("default", "<login> login account is null [%d][%d]", _accountId, fd);
		return;
	}
	if (login_account->GetLoginStatus() != ELOGIN_STATUS_CHECKACCOUNT_END)
	{
		LOG_ERROR("default", "<login> login account status err [%d][%d]", _accountId, fd);
		return;
	}

	// 判断选择的英雄是否正确
	login_account->ChangeLoginStatus(ELOGIN_STATUS_REGISTER_BEGIN);
	Json::Value j_msg;
	j_msg["msgid"] = l2g_create_player_req;
	j_msg["account"] = _accountId;
	j_msg["name"] = _name;
	j_msg["heroId"] = _heroId;
	j_msg["udid"] = _udid;
	j_msg["appKey"] = _appKey;
	j_msg["appSecret"] = _appSecret;
	j_msg["pubKey"] = _pubKey;
	std::string s = JsonWriter(j_msg);
	send_2_game(l2g_create_player_req, s);
	return;
}

void CLoginLogic::G2LPlayerRegisterResponse(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	const Json::Value& m_jv = msg.GetJsonValue();

	int32_t ret = m_jv["ret"].asInt();
	int32_t account = m_jv["account"].asInt();
	CLoginAccount* login_account = CLoginLogic::GetInstance().GetLoginAccount(account);
	if (login_account == NULL)
	{
		LOG_ERROR("default", "login account is null[%d]", account);
		return;
	}
	login_account->ChangeLoginStatus(ELOGIN_STATUS_REGISTER_END);
	Json::Value response;
	response = m_jv;
	response["msgid"] = login_create_player_ret;
	response["ret"] = ret;
	std::string res = JsonWriter(response);
	LoginServer::GetInstance().client_msg_dispatch(res, login_account->GetSocketFD(), login_create_player_ret);
	if (ret != ::common::SUCCEED)
	{
		login_account->ChangeLoginStatus(ELOGIN_STATUS_CHECKACCOUNT_END);
	}
	else
	{
		CLoginLogic::GetInstance().DespawnClient(login_account->GetSocketFD());
	}
}

void CLoginLogic::DoRegisterResponse(int32_t ret, int32_t fd)
{
	Json::Value response;
	response["ret"] = ret;
	response["msgid"] = login_create_player_ret;
	std::string res = JsonWriter(response);
	LoginServer::GetInstance().client_msg_dispatch(res, fd, login_create_player_ret);
}


int CLoginLogic::CheckAccount(int32_t account_id, int32_t fd)
{
	CLoginAccount* login_account = CLoginLogic::GetInstance().GetLoginAccount(account_id);
	if (login_account != NULL)
	{
		// 上一次登陆到现在超过十秒, 则将现在的删除
		if (CUR_SEC - login_account->GetLoginTime() >= 10)
		{
			LOG_INFO("default", "login_account[%d][%d] is timeout ", login_account->GetAccountID(), login_account->GetSocketFD());
			if (DespawnClient(login_account->GetSocketFD()) == 0)
			{
				login_account = NULL;
			}
			else
			{
				LOG_INFO("default", "timeout del err");
				return ::common::ERR_LOGIN_IS_LOGINING;
			}
		}
		else
		{
			LOG_ERROR("default", "account[%d] is login or register!", account_id);
			return ::common::ERR_LOGIN_IS_LOGINING;
		}
	}

	return ::common::SUCCEED;
}

void CLoginLogic::G2LPlayerCheckAccountResponse(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	const Json::Value& m_jv = msg.GetJsonValue();
	int32_t ret = m_jv["ret"].asInt();
	int32_t account = m_jv["account"].asInt();
	CLoginAccount* login_account = CLoginLogic::GetInstance().GetLoginAccount(account);
	if (login_account == NULL)
	{
		LOG_ERROR("default", "cant find CLoginAccount[%d]", account);
		return;
	}
	if (ret == ::common::SUCCEED)
	{
		login_account->ChangeLoginStatus(ELOGIN_STATUS_CHECKACCOUNT_END);
	}
	Json::Value response;
	response["msgid"] = login_check_account_ret;
	response["ret"] = ret;
	response["account"] = account;
	response["playerId"] = m_jv["playerId"].asInt();
	response["name"] = m_jv["name"].asString();
	response["heroId"] = m_jv["heroId"].asInt();
	response["areaId"] = m_jv["areaId"].asInt();

	std::string res = JsonWriter(response);
	LoginServer::GetInstance().client_msg_dispatch(res, login_account->GetSocketFD(), login_check_account_ret);
	if (ret != ::common::SUCCEED)
	{
		CLoginLogic::GetInstance().DespawnClient(login_account->GetSocketFD());
	}
}

CLoginAccount* CLoginLogic::GetLoginAccount(int32_t account)
{
	auto iter = account_id_map_.find(account);
	if (iter == account_id_map_.end())
	{
		return NULL;
	}
	return CLoginObjManager::GetInstance().GetObjectByID< CLoginAccount >(iter->second);
}

void CLoginLogic::G2LPlayerLoginResponse(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	const Json::Value& m_jv = msg.GetJsonValue();
	int32_t ret = m_jv["ret"].asInt();
	int32_t playerId = m_jv["playerId"].asInt();
	int32_t account = m_jv["account"].asInt();

	CLoginAccount* login_account = CLoginLogic::GetInstance().GetLoginAccount(account);
	if (login_account == NULL)
	{
		LOG_ERROR("default", "<Login> player[%d][%d] login err", account, playerId);
		return;
	}

	login_account->ChangeLoginStatus(ELOGIN_STATUS_LOGIN_END);

	Json::Value client_response;
	client_response = m_jv;
	client_response["msgid"] = login_player_login_ret;
	std::string client_res = JsonWriter(client_response);
	LoginServer::GetInstance().client_msg_dispatch(client_res, login_account->GetSocketFD(), login_player_login_ret);

	CLoginLogic::GetInstance().DespawnClient(login_account->GetSocketFD());
}

int CLoginLogic::AddLoginAccount(CLoginAccount& account)
{
	std::pair< TObjIDMap::iterator, bool > insert_pair = account_id_map_.insert(TObjIDMap::value_type(account.GetAccountID(), account.get_id()));
	if (insert_pair.second == false)
	{
		LOG_ERROR("default", "insert player %d %d %d into role_map faild", account.GetAccountID(), account.GetSocketFD(), account.get_id());
		return ::common::ERR_UNKNOWN;
	}

	insert_pair = socket_id_map_.insert(TSocketObjIDMap::value_type(account.GetSocketFD(), account.get_id()));
	if (insert_pair.second == false)
	{
		LOG_ERROR("default", "insert player %d %d %d into role_map faild", account.GetAccountID(), account.GetSocketFD(), account.get_id());
		return ::common::ERR_UNKNOWN;
	}

	return ::common::SUCCEED;
}

void CLoginLogic::SendCheckAccountRes(int32_t fd, int32_t ret, int32_t account)
{
	Json::Value response;
	response["msgid"] = login_check_account_ret;
	response["ret"] = ret;
	response["account"] = account;
	response["playerId"] = 0;
	response["name"] = "";
	response["heroId"] = 0;
	response["areaId"] = 0;

	std::string res = JsonWriter(response);
	LoginServer::GetInstance().client_msg_dispatch(res, fd, login_check_account_ret);
}

int32_t CLoginLogic::CheckConnect(int32_t account_id, int32_t fd)
{
	auto iter = socket_id_map_.find(fd);
	if (iter == socket_id_map_.end())
	{
		return ::common::ERR_LOGIN_TIME_OUT;
	}
	CLoginAccount* login_account = CLoginObjManager::GetInstance().GetObjectByID<CLoginAccount>(iter->second);
	if (login_account == NULL)
	{
		return ::common::ERR_LOGIN_TIME_OUT;
	}
	if ( login_account->GetAccountID() != account_id )
	{
		return ::common::ERR_LOGIN_TIME_OUT;
	}
	return ::common::SUCCEED;
}

int32_t CLoginLogic::DespawnClient(int fd_)
{
	TSocketObjIDMap::iterator iter = socket_id_map_.find(fd_);
	if (iter == socket_id_map_.end())
	{
		return -1;
	}
	CLoginAccount* login_account = CLoginObjManager::GetInstance().GetObjectByID< CLoginAccount >(iter->second);
	if (login_account == NULL)
	{
		LOG_ERROR("default", "login_account is null[%d][%d]", fd_, iter->second);
		socket_id_map_.erase(iter);
		return -1;
	}
	int32_t account = login_account->GetAccountID();
	TObjIDMap::iterator iter_account = account_id_map_.find(account);
	if (iter_account == account_id_map_.end())
	{
		socket_id_map_.erase(iter);
		LOG_ERROR("default", "cant find login_account account[%d]", account);
		return -1;
	}
	CLoginObjManager::GetInstance().DestoryObject(login_account->get_id());
	socket_id_map_.erase(iter);
	account_id_map_.erase(iter_account);
	return 0;
}

void CLoginLogic::DoLoginResponse(int32_t ret, uint32_t fd)
{
	Json::Value response;
	response["ret"] = ret;
	response["msgid"] = login_player_login_ret;
	std::string res = JsonWriter(response);
	LoginServer::GetInstance().client_msg_dispatch(res, fd, login_check_account_ret);
}

void CLoginLogic::G2LGameServerStartNotify(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	CLoginLogic::GetInstance().set_game_start();
	LOG_INFO("default", "game server is start !");
}

void CLoginLogic::C2LGamePlayerNumReport(const common::CProxyHead& head, const CJsonMessageBase& msg)
{
	const Json::Value& m_jv = msg.GetJsonValue();
	int32_t playernum = m_jv["playernum"].asInt();
	int32_t now_time = CUR_SEC;

	CLoginQueueMgr::GetInstance().update_player_online(playernum, now_time);
	LOG_DEBUG("default", "game update player num [%d], time[%d]", playernum, now_time);
}

CLoginAccount* CLoginLogic::GetLoginAccountByFd(int32_t socketid)
{
	auto iter = socket_id_map_.find(socketid);
	if (iter == socket_id_map_.end())
	{
		return NULL;
	}
	CLoginAccount* login_account = CLoginObjManager::GetInstance().GetObjectByID< CLoginAccount >(iter->second);
	return login_account;
}

void CLoginLogic::TickUpdate()
{

}

int CLoginLogic::AccountLoginBegin(int32_t account_id, int32_t fd)
{
	CLoginAccount* login_account = CLoginLogic::GetInstance().GetLoginAccount(account_id);
	if (login_account != NULL)
	{
		// 上一次登陆到现在超过十秒, 则将现在的删除
		if (CUR_SEC - login_account->GetLoginTime() >= 10)
		{
			LOG_INFO("default", "login_account[%d][%d] is timeout ", login_account->GetAccountID(), login_account->GetSocketFD());
			if (DespawnClient(login_account->GetSocketFD()) == 0)
			{
				login_account = NULL;
			}
			else
			{
				LOG_INFO("default", "timeout del err");
				return ::common::ERR_LOGIN_IS_LOGINING;
			}
		}
		else
		{
			LOG_ERROR("default", "account[%d] is login or register!", account_id);
			return ::common::ERR_LOGIN_IS_LOGINING;
		}
	}

	login_account = CLoginObjManager::GetInstance().CreateObject< CLoginAccount >(LOGINOBJTYPE_LOGINACCOUNT);
	if (login_account == NULL)
	{
		LOG_ERROR("default", "create login account failed![%d]", account_id);
		return ::common::ERR_LOGIN_CREATE_DATE_ERR;
	}
	login_account->SetLoginTime(CUR_SEC);
	login_account->SetSocketFD(fd);
	login_account->SetAccountID(account_id);
	int32_t ret = CLoginLogic::GetInstance().AddLoginAccount(*login_account);
	if (ret != ::common::SUCCEED)
	{
		DespawnClient(fd);
		return ret;
	}
	login_account->ChangeLoginStatus(ELOGIN_STATUS_CHECKACCOUNT_BEGIN);
	Json::Value request;
	request["account"] = account_id;
	std::string req = JsonWriter(request);
	send_2_game(l2g_login_check_account_req, req);
	return ::common::SUCCEED;
}

void CTestTimer::TimerActive()
{
	LOG_INFO("default", "Test Timer is Active! time:%d", CUR_SEC);
	TimerStart();

	char sql[512] = { 0 };
	snprintf(sql, sizeof(sql), "select count(*) from tb_player_info");
	Json::Value request;
	request["sql"] = std::string(sql);

	std::string sendstr = JsonWriter(request);
	//send_2_platform(ID_DBSqlExecResquest, sendstr);
}
